package com.zu.commu.gsm1_0;

import BestMail.smssend;
import com.zu.commu.context.ServerContext;
import com.zu.commu.gsm1_0.handler.GReceiveHandler;
import com.zu.commu.gsm1_0.handler.GSendHandler;
import com.zu.commu.gsm1_0.interf.Message;
import com.zu.commu.gsm1_0.interf.ReceiveHandler;
import com.zu.commu.gsm1_0.interf.SendHandler;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Iterator;

public class GSMCenter
{
  private static Logger logger = Logger.getLogger(GSMCenter.class);
  private static GSMCenter instance;
  private int status;
  private smssend sender;
  private ArrayList<Message> messageList;
  private SendThread sendThread;
  private ReceiveThread receiveThread;
  private SendHandler sendHandler;
  private ReceiveHandler receiveHandler;
  public static boolean GSMModelConnected = false;

  public static GSMCenter getInstance(SendHandler shandler, ReceiveHandler rhandler)
    throws RuntimeException
  {
    if (instance == null) {
      synchronized (GSMCenter.class) {
        if (instance == null) {
          instance = new GSMCenter(shandler, rhandler);
        }
      }
    }
    return instance;
  }

  public static GSMCenter getInstance()
    throws RuntimeException
  {
    if (instance == null) {
      synchronized (GSMCenter.class) {
        if (instance == null) {
          SendHandler shandler = new GSendHandler();
          ReceiveHandler rhandler = new GReceiveHandler();
          instance = new GSMCenter(shandler, rhandler);
        }
      }
    }
    return instance;
  }

  private GSMCenter(SendHandler shandler, ReceiveHandler rhandler)
    throws RuntimeException
  {
    this.status = 1;
    this.messageList = new ArrayList();
    this.sendThread = new SendThread();
    this.sendThread.start();
    this.receiveThread = new ReceiveThread();
    this.receiveThread.start();

    this.sendHandler = shandler;

    this.receiveHandler = rhandler;
    checkSMSStatus();
  }

  public void openSMSCenter()
  {
    this.status = 1;
  }

  public void closeSMSCenter()
  {
    this.status = 0;
  }

  public synchronized void checkSMSStatus()
    throws RuntimeException
  {
    if (this.sender == null) {
      this.sender = new smssend();
    }
    if (!this.sender.GSMModemIsConn())
      connect();
  }

  private void connect()
    throws RuntimeException
  {
    String com = ServerContext.GSMServerDevice;

    String baud = ServerContext.GSMServerBaud+"";

    String cn = ServerContext.GSMServerSN;

    String sninfo = this.sender.GSMModemGetSnInfoNew(com, baud);
    if (sninfo == null) {
      throw new RuntimeException(this.sender.GSMModemGetErrorMsg());
    }
    logger.info("短信猫标识码=" + sninfo);
    logger.info("短信猫:connecting ... ...");
    if (!this.sender.GSMModemInitNew(com, baud, null, "GSM", false, cn)) {
      throw new RuntimeException(this.sender.GSMModemGetErrorMsg());
    }
    logger.info("当前通讯端口   = " + this.sender.GSMModemGetDevice());
    logger.info("当前通讯波特率 = " + this.sender.GSMModemGetBaudrate());

    GSMModelConnected = true;
  }

  public void release()
  {
    this.sender.GSMModemRelease();
  }

  public void setMessage(Message message)
  {
    synchronized (this.messageList) {
      this.messageList.add(message);
    }
  }

  public void setMessage(ArrayList<Message> list)
  {
    Iterator it = list.iterator();
    synchronized (this.messageList) {
      while (it.hasNext())
        this.messageList.add((Message)it.next());
    }
  }

  private Message popMessage()
  {
    synchronized (this.messageList) {
      if (this.messageList.size() == 0) {
        return null;
      }
      return (Message)this.messageList.remove(0);
    }
  }

  private synchronized boolean doSend(Message message)
  {
    try
    {
      checkSMSStatus();
      logger.info("send: telephone=" + message.simNo + ", code=" + message.code + ", content=" + message.content);
      byte[] sendContents = (byte[])null;

      switch (message.code) {
      case 8:
        sendContents = smssend.getUNIByteArray(message.content);
        break;
      default:
        sendContents = message.content.getBytes();
      }

      if (this.sender.GSMModemSMSsend(null, message.code, sendContents, message.simNo, false))
        logger.info("send: Success!");
      else {
        throw new RuntimeException(this.sender.GSMModemGetErrorMsg());
      }

      if (this.sendHandler != null) {
        this.sendHandler.handle(message);
      }

      try
      {
        Thread.sleep(500L);
      } catch (InterruptedException localInterruptedException) {
      }
      return true;
    } catch (Exception ex) {
      logger.error(ex.getMessage());
    }return false;
  }

  private synchronized boolean doReceive()
  {
    try
    {
      checkSMSStatus();

      String[] allmsg = this.sender.GSMModemSMSReadAll(0);
      if (allmsg != null) {
        for (int i = 0; i < allmsg.length; i++)
          if (allmsg[i] != null) {
            String[] tmp = allmsg[i].split("#");
            if ((tmp == null) || (tmp.length != 3)) {
              logger.error("出错，短信格式不正确,该短信: " + allmsg[i]);
            }
            else
            {
              String simNo = tmp[0];
              String code = tmp[1];
              String content = tmp[2];
              if ((content != null) && (code.equalsIgnoreCase("8"))) {
                content = smssend.HexToBuf(content).trim();
              }
              debug(simNo, content);
              logger.info("recieve: telephone=" + simNo + ",code=" + code + ", content=" + content);

              if (this.receiveHandler != null)
                this.receiveHandler.handle(new Message(simNo, content, Integer.parseInt(code), null));
            }
          }
      }
      return true;
    } catch (Exception ex) {
      logger.error(ex.getMessage());
    }return false;
  }

  private void debug(String simNo, String message)
  {
    if ((ServerContext.GSMDebug != null) && (ServerContext.GSMDebug.booleanValue())) {
      String dSimNo = ServerContext.GSMDebugSimNO;
      if ((dSimNo == null) || (dSimNo.equals(""))) {
        String path = ServerContext.DebugSavePath;
        DebugSave ds = DebugSave.getInstance(path);
        ds.save(simNo, message);
      }
      else if (simNo.endsWith(dSimNo)) {
        String path = ServerContext.DebugSavePath;
        DebugSave ds = DebugSave.getInstance(path);
        ds.save(simNo, message);
      }
    }
  }

  private class SendThread extends Thread
  {
    public SendThread()
    {
      setDaemon(true);
    }
    public void run() {
      while (true) {
        if (GSMCenter.this.status == 1) {
          Message message = GSMCenter.this.popMessage();
          while (message != null) {
            GSMCenter.this.doSend(message);
            message = GSMCenter.this.popMessage();
          }
        }
        try {
          Thread.sleep(1000L);
        }
        catch (Exception localException)
        {
        }
      }
    }
  }

  private class ReceiveThread extends Thread
  {
    public ReceiveThread()
    {
      setDaemon(true);
    }
    public void run() {
      while (true) {
        if (GSMCenter.this.status == 1)
          GSMCenter.this.doReceive();
        try
        {
          Thread.sleep(10000L);
        }
        catch (Exception localException)
        {
        }
      }
    }
  }
}